#ifndef __CHEBYSHEVRON__
#define __CHEBYSHEVRON__


#include "cxfloat.h"
#include <vector>
#include "Pincushion.h"


class Mobius;


class Chebyshevron
{
  public:
    Chebyshevron(Mobius* mob, std::vector<SeamStress::Seamstress*>* ss, unsigned long int nt=1, mpfr_prec_t p=4);
    ~Chebyshevron();
    
    //given coefs of a polynomial of order N-1 (N terms), calculate the polynomial at the M chebyshev points cos(pi*(2*k+1)/2*M), k in [0,M) with M being the smallest power of 2 which is >= N, and store the results in vals
    void valsFromCoefs(const std::vector<cxfloat>& coefs, std::vector<cxfloat>& vals);
    
    //given values at M chebyshev points, with M a power of 2, cos(pi*(2*k+1)/2*M), k in [0,M), calculate the coefficients of the polynomial with M terms, in monomial form, which evaluates to those values, and store the result in coefs
    void coefsFromVals(const std::vector<cxfloat>& vals, std::vector<cxfloat>& coefs);
    
    //calculate the Chebyshev polynomial of order N-1
    void chebyPoly(unsigned long int N, refloat_vec& coefs);
    
    Mobius* getMobius();
    
    
    void scaleVarByUnityRoot(void* arg);
    void scaleVarByUnityRootInverse(void* arg);
    void finalizeVals(void* arg);
    void initializeVals(void* arg);
    void chebyPolyInit(void* arg);
    
  protected:
    SeamStress::Pincushion<Chebyshevron> pins;
    
    mp_prec_t prec;
    
    unsigned long int nthreads;
    
    Mobius* mobius;
    
    
  private:
    std::vector<cxfloat> tempvec1;
    std::vector<cxfloat> tempvec2;
    std::vector<cxfloat> tempvec3;
    
    //one entry per thread
    std::vector<cxfloat> threadvec1;
    
    cxfloat tempval1, tempval2;
    
    cxfloat one, negone;
    
    unsigned long int thread_tot;
    unsigned long int thread_var1;
    unsigned long int thread_var2;
    unsigned long int thread_var3;
    
    std::vector<cxfloat>* tempvecpointer1;
};

inline Mobius* Chebyshevron::getMobius(){return mobius;}



#endif
